package us.gaaoc.framework.webapp.backingbeans.admin;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException;

import org.apache.log4j.Logger;
import org.hibernate.Hibernate;

import us.gaaoc.framework.model.Address;
import us.gaaoc.framework.model.AddressCategory;
import us.gaaoc.framework.model.AddressType;
import us.gaaoc.framework.model.CaseRecord;
import us.gaaoc.framework.model.Court;
import us.gaaoc.framework.model.OrgParticipants;
import us.gaaoc.framework.model.ParticipantRelationship;
import us.gaaoc.framework.model.Person;
import us.gaaoc.framework.model.PersonAddress;
import us.gaaoc.framework.model.PersonParticipants;
import us.gaaoc.framework.util.CaseFilingPersistor;
import us.gaaoc.framework.util.DateUtil;
import us.gaaoc.framework.util.LocalCaseInformation;
import us.gaaoc.framework.webapp.backingbeans.BaseBackingBean;
import us.gaaoc.framework.webapp.util.Messages;
import us.gaaoc.cms.Exporter;
import us.gaaoc.cms.Importer;
import us.gaaoc.cms.sustain.vo.CaseFiling;
import us.gaaoc.cms.sustain.vo.CaseParty;
import us.gaaoc.cms.sustain.ImportUtilFactory;

public class UpdateParties extends BaseBackingBean {
	/**
	 * properties
	 */
	private CaseRecord caseRecord;

	// private String filerName;

	// private Date courtDate;
	/**
	 * Data Models for the personParticipants
	 */
	private DataModel initiatingPartyPersonModel;

	private DataModel defendentPartyPersonModel;

	private DataModel witnessPersonModel;

	private DataModel initiatingPartyOrganizationDataModel;

	private Logger LOG = Logger.getLogger(EditParticipants.class);

	private FacesMessage message;

	private String courtUuid;
	
	private String docketId;

	private Person person;
	private Address address;

	private String firstName;
	private String middleName;
	private String lastName;
	private String suffixName;
	private Date dob;
	private String streetFullText;
	private String streetExtensionText;
	private String cityName;
	private String state;
	private String zipCode;

	private ArrayList<SelectItem> personTypes;
	private String selectedType;

	/**
	 * Constructor
	 * 
	 */
	public UpdateParties() {
		this.loadData();

		person = new Person();
		address = new Address();
		personTypes = new ArrayList<SelectItem>();

		List<ParticipantRelationship> l = this.getModelFacade()
				.getAllParticipantRelationshipCodes();

		for (ParticipantRelationship p : l) {
			System.out.println("code: " + p.getCode() + " desc: "
					+ p.getDescription());
			personTypes.add(new SelectItem(String.valueOf(p.getCode()), p
					.getDescription()));
		}

		selectedType = personTypes.get(0).getLabel();

		LOG.debug("in constructor");
		LOG.debug("person is " + person);
		//return " ";
	}

	/**
	 * This method loads the data from the database for the particular filing.
	 * 
	 */
	@SuppressWarnings("unchecked")
	private void loadData() {
		Map sessionMap = this.getFacesContext().getExternalContext()
				.getSessionMap();

		courtUuid = (String) sessionMap.get("courtUuid");

		String caseUuid = (String) sessionMap.get("caseUuid");
		CaseRecord c = (CaseRecord) this.getModelFacade().findCaseRecordById(
				caseUuid, courtUuid);

		// Uncommented to fix issue:
		// b7006e6c-695c-11dd-945f-00301b45ff56
		Hibernate.initialize(c.getPersonParticipants());
		Hibernate.initialize(c.getOrgParticipants());
		Hibernate.initialize(c.getDocuments());
		// ---------------------

		List<PersonParticipants> pParticipantsList = c.getPersonParticipants();
		List<OrgParticipants> oParticipantsList = c.getOrgParticipants();

		List initiatingPartyOrganizationList = new ArrayList();

		// for initiating party person list
		List initiatingPartyPersonList = new ArrayList();

		// for defendant party person list
		List defendentPartyPersonList = new ArrayList();

		// for witness person list
		List witnessPersonList = new ArrayList();

		for (OrgParticipants o : oParticipantsList) {
			if (o.getRelationship().getCode() == 1)
				initiatingPartyOrganizationList.add(o);
		}

		for (PersonParticipants o : pParticipantsList) {
			if (o.getRelationship().getCode() == 1)
				initiatingPartyPersonList.add(o);
			else if (o.getRelationship().getCode() == 2)
				defendentPartyPersonList.add(o);
			else if (o.getRelationship().getCode() == 3)
				witnessPersonList.add(o);
		}

		initiatingPartyOrganizationDataModel = new ListDataModel();
		initiatingPartyOrganizationDataModel
				.setWrappedData(initiatingPartyOrganizationList);

		initiatingPartyPersonModel = new ListDataModel();
		initiatingPartyPersonModel.setWrappedData(initiatingPartyPersonList);

		defendentPartyPersonModel = new ListDataModel();
		defendentPartyPersonModel.setWrappedData(defendentPartyPersonList);

		witnessPersonModel = new ListDataModel();
		witnessPersonModel.setWrappedData(witnessPersonList);

		this.setCaseRecord(c);
	}

	public void updateParties() throws Exception {
		Map sessionMap = this.getFacesContext().getExternalContext()
		.getSessionMap();

		courtUuid = (String) sessionMap.get("courtUuid");
		Person personSignedIn = (Person) sessionMap.get("person");
		
		String caseUuid = (String) sessionMap.get("caseUuid");
		CaseRecord c = (CaseRecord) this.getModelFacade().findCaseRecordById(
				caseUuid, courtUuid);
		
		// for initiating party person list
		List<PersonParticipants> initiatingPartyPersonList = new ArrayList<PersonParticipants>();
		List<PersonParticipants> pParticipantsList = getCaseRecord().getPersonParticipants();
		for (PersonParticipants o : pParticipantsList) {
			if (o.getRelationship().getCode() == 1)
				initiatingPartyPersonList.add(o);
		}

		System.out.println("The parties will be updated in Sustain");
		String filingUuid = null;
		// TODO: pullCaseFromSustain() from ExistingFilingPage.java
		// If not in GAJE system, look in Court's Case Management System
		Court court = this.getCaseRecord().getCourt();
		String casDivID = null;
		casDivID = LocalCaseInformation.getDivID(court.getUuid());
		CaseFiling filing = null;
		String docketID = caseRecord.getCaseTrackingId(); 

		
		
		Exporter export = new Exporter(courtUuid);
		try {
			
			filing = export.doExportNoOfficial(docketID, casDivID, courtUuid,"SYSTEM");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw e;
		}
		
		
		List<CaseParty> initiatingPartyFromSustain = filing.getInitatingPartyPersonList();
		int i = 0;
		Importer importer = new Importer(courtUuid);

		List<CaseParty> newChildren = new java.util.LinkedList();
		
		for(PersonParticipants pp : initiatingPartyPersonList)
		{
			us.gaaoc.cms.sustain.vo.Person csp;
			
			CaseParty cp;
			try {
				
				csp = initiatingPartyFromSustain.get(i).getPerson();
				cp = initiatingPartyFromSustain.get(i);
				//log.info("adding existing party");
			}catch(IndexOutOfBoundsException exn)
			{
				//log.info("Creating new person!");
				csp = new us.gaaoc.cms.sustain.vo.Person(pp.getPerson().getFirstName(),pp.getPerson().getLastName());
				cp = new CaseParty();
				cp.setCmsTypeCode("PLF");
				
			}
			//log.info(pp.getPerson().getFullName());
			csp.setFirstName(pp.getPerson().getFirstName());
			csp.setLastName(pp.getPerson().getLastName());
			csp.setMiddleName(pp.getPerson().getMiddleName());
			csp.setSuffix(pp.getPerson().getSuffixName());
			cp.setPerson(csp);
			newChildren.add(cp);
			i++;
		}
		
		/*
		for (CaseParty cp : initiatingPartyFromSustain) {
			us.gaaoc.cms.sustain.vo.Person csp = cp.getPerson();
			PersonParticipants pp = initiatingPartyPersonList.get(i);
			csp.setFirstName(pp.getPerson().getFirstName());
			csp.setLastName(pp.getPerson().getLastName());
			csp.setMiddleName(pp.getPerson().getMiddleName());
			csp.setSuffix(pp.getPerson().getSuffixName());
			cp.setPerson(csp);
			i++;
		}
		*/
		filing.setInitatingPartyPersonList(newChildren);
		
		int partyCount = initiatingPartyFromSustain.size();
		try {

			importer.updateChildren(filing,newChildren);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		

	}
	
	/*
	
	public String updateParties() {
		Map sessionMap = this.getFacesContext().getExternalContext()
				.getSessionMap();

		courtUuid = (String) sessionMap.get("courtUuid");
		Person personSignedIn = (Person) sessionMap.get("person");

		String caseUuid = (String) sessionMap.get("caseUuid");
		CaseRecord c = (CaseRecord) this.getModelFacade().findCaseRecordById(
				caseUuid, courtUuid);
		// for initiating party person list
		List<PersonParticipants> initiatingPartyPersonList = new ArrayList<PersonParticipants>();
		List<PersonParticipants> pParticipantsList = c.getPersonParticipants();
		for (PersonParticipants o : pParticipantsList) {
			if (o.getRelationship().getCode() == 1)
				initiatingPartyPersonList.add(o);
		}

		System.out.println("The parties will be updated in Sustain");
		String filingUuid = null;
		// TODO: pullCaseFromSustain() from ExistingFilingPage.java
		// If not in GAJE system, look in Court's Case Management System
		Court court = this.getModelFacade().findCourt(courtUuid);
		String casDivID = null;
		casDivID = LocalCaseInformation.getDivID(court.getUuid());
		CaseFiling filing = null;
		String docketID = c.getCaseTrackingId(); 

		
		
		Exporter export = new Exporter(courtUuid);
		try {
			
			filing = export.doExportNoOfficial(docketID, casDivID, courtUuid,
					personSignedIn.getUuid());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "Stay";
		}
		
		List<CaseParty> newChildren = new java.util.LinkedList();
		List<CaseParty> initiatingPartyFromSustain = filing.getInitatingPartyPersonList();
		int i = 0;
		for(PersonParticipants pp : initiatingPartyPersonList)
		{
			us.gaaoc.cms.sustain.vo.Person csp;
			
			CaseParty cp;
			try {
				
				csp = initiatingPartyFromSustain.get(i).getPerson();
				cp = initiatingPartyFromSustain.get(i);
			}catch(IndexOutOfBoundsException exn)
			{
				csp = new us.gaaoc.cms.sustain.vo.Person(pp.getPerson().getFirstName(),pp.getPerson().getLastName());
				cp = new CaseParty();
				cp.setCmsTypeCode("PLF");//TODO: make CmsTypeCode dynamic.
				
			}
			csp.setFirstName(pp.getPerson().getFirstName());
			csp.setLastName(pp.getPerson().getLastName());
			csp.setMiddleName(pp.getPerson().getMiddleName());
			csp.setSuffix(pp.getPerson().getSuffixName());
			cp.setPerson(csp);
			newChildren.add(cp);
			i++;
		}
		
		filing.setInitatingPartyPersonList(initiatingPartyFromSustain);
		Importer importer = new Importer(courtUuid);
		int partyCount = initiatingPartyFromSustain.size();
		try {

			importer.updateChildren(filing,initiatingPartyFromSustain);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return "Stay";
	}
	*/

	public void validateDate(FacesContext context, UIComponent component,
			Object value) throws ValidatorException, Exception {
		java.util.Date newValue = (java.util.Date) value;

		Calendar c = new GregorianCalendar();
		c.setTime(newValue);

		int date = c.get(Calendar.DATE);
		c.set(Calendar.DATE, date + 1);
		newValue = c.getTime();

		if (!isValidDate(newValue)) {
			message.setSeverity(FacesMessage.SEVERITY_ERROR);
			throw new ValidatorException(message);
		}
	}

	/**
	 * Method to check date to ensure that it is not a future date.
	 */
	protected boolean isValidDate(java.util.Date value) throws Exception {
		boolean validField = false;
		if (value.compareTo(DateUtil.getCurrentDate()) < 0) {
			validField = false;
			message = Messages.getMessage(
					"us.gaaoc.framework.webapp.util.errorMessage",
					"incorrectDate", null);
			message.setDetail(message.getDetail());
			message.setSeverity(FacesMessage.SEVERITY_ERROR);
		} else {
			validField = true;
		}
		return validField;
	}

	/**
	 * This method navigates user to the import filing page.
	 * 
	 * @return String
	 */
	public String gotoImportFiling() {
		return "gotoImportFiling";
	}

	/**
	 * This method navigates user to the reject filing page.
	 * 
	 * @return String
	 */
	public String gotoRejectFiling() {
		return "gotoRejectFiling";
	}

	/**
	 * This method navigates user to the previous page.
	 * 
	 * @return
	 */
	public String back() {
		Map sessionMap = this.getFacesContext().getExternalContext()
				.getSessionMap();
		String fromPage = (String) sessionMap.get("from");
		sessionMap.remove("from");
		sessionMap.remove("caseUuid");

		if (fromPage.equalsIgnoreCase("ChildEnforcementCaseTypePage")) {
			return "childEnforcement";
		} else if (fromPage.equalsIgnoreCase("ReceivedFilingPage")) {
			return "received";
		} else if (fromPage.equalsIgnoreCase("RejectedFilingPage")) {
			return "rejected";
		} else if (fromPage.equalsIgnoreCase("ImportedFilingPage")) {
			return "imported";
		} else if (fromPage.equalsIgnoreCase("DisposedFilingPage")) {
			return "disposed";
		} else if (fromPage.equalsIgnoreCase("TransmissionErrorFilingPage")) {
			return "transmissionError";
		} else if (fromPage.equalsIgnoreCase("ServedFilingPage")) {
			return "served";
		} else if (fromPage.equalsIgnoreCase("NonServedFilingPage")) {
			return "served";
		} else if (fromPage.equalsIgnoreCase("NewFilingPage")) {
			return "newFiling";
		} else if (fromPage.equalsIgnoreCase("AppellateCaseTypePage")) {
			return "appellate";
		} else if (fromPage.equalsIgnoreCase("CivilCaseTypePage")) {
			return "civil";
		} else if (fromPage.equalsIgnoreCase("MainPage")) {
			return "adminHome";
		} else if (fromPage.equalsIgnoreCase("searchPage")) {
			return "searchPage";

		} else
			return "";
	}

	/**
	 * @param initiatingPartyOrganizationDataModel
	 *            The initiatingPartyOrganizationDataModel to set.
	 */
	public void setInitiatingPartyOrganizationDataModel(
			DataModel initiatingPartyOrganizationDataModel) {
		this.initiatingPartyOrganizationDataModel = initiatingPartyOrganizationDataModel;
	}

	/**
	 * @return Returns the caseRecord.
	 */
	public CaseRecord getCaseRecord() {
		return caseRecord;
	}

	/**
	 * Setter for property caseRecord
	 * 
	 * @param caseRecord
	 */
	public void setCaseRecord(CaseRecord caseRecord) {
		this.caseRecord = caseRecord;
	}

	/**
	 * Getter for property defendentPartyPersonModel
	 * 
	 * @return defendentPartyPersonModel
	 */
	public DataModel getDefendentPartyPersonModel() {
		return defendentPartyPersonModel;
	}

	/**
	 * Setter for property defendentPartyPersonModel
	 * 
	 * @param defendentPartyPersonModel
	 */
	public void setDefendentPartyPersonModel(DataModel defendentPartyPersonModel) {
		this.defendentPartyPersonModel = defendentPartyPersonModel;
	}

	/**
	 * Getter for property initiationgPartyPersonModel
	 * 
	 * @return initiatingPartyPersonModel
	 */
	public DataModel getInitiatingPartyPersonModel() {
		return initiatingPartyPersonModel;
	}

	/**
	 * Setter for property initiatingPartyPersonmodel
	 * 
	 * @param initiatingPartyPersonModel
	 */
	public void setInitiatingPartyPersonModel(
			DataModel initiatingPartyPersonModel) {
		this.initiatingPartyPersonModel = initiatingPartyPersonModel;
	}

	/**
	 * Getter for property initiatingPartyOrganizationDataModel
	 * 
	 * @return initiatingPartyOrganizationDataModel
	 */
	public DataModel getInitiatingPartyOrganizationDataModel() {
		return initiatingPartyOrganizationDataModel;
	}

	/**
	 * Getter for property witnessPersonModel
	 * 
	 * @return
	 */
	public DataModel getWitnessPersonModel() {
		return witnessPersonModel;
	}

	/**
	 * Setter for property witnessPersonModel
	 * 
	 * @param witnessPersonModel
	 */
	public void setWitnessPersonModel(DataModel witnessPersonModel) {
		this.witnessPersonModel = witnessPersonModel;
	}

	public FacesMessage getMessage() {
		return message;
	}

	public void setMessage(FacesMessage message) {
		this.message = message;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getMiddleName() {
		return middleName;
	}

	public void setMiddleName(String middleName) {
		this.middleName = middleName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getSuffixName() {
		return suffixName;
	}

	public void setSuffixName(String suffixName) {
		this.suffixName = suffixName;
	}

	public Date getDob() {
		return dob;
	}

	public void setDob(Date dob) {
		this.dob = dob;
	}

	public String getStreetFullText() {
		return streetFullText;
	}

	public void setStreetFullText(String streetFullText) {
		this.streetFullText = streetFullText;
	}

	public String getStreetExtensionText() {
		return streetExtensionText;
	}

	public void setStreetExtensionText(String streetExtensionText) {
		this.streetExtensionText = streetExtensionText;
	}

	public String getCityName() {
		return cityName;
	}

	public void setCityName(String cityName) {
		this.cityName = cityName;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public String getZipCode() {
		return zipCode;
	}

	public void setZipCode(String zipCode) {
		this.zipCode = zipCode;
	}

	public void setPersonTypes(ArrayList<SelectItem> personTypes) {
		this.personTypes = personTypes;
	}

	public List<SelectItem> getPersonTypes() {
		return personTypes;
	}

	public void setSelectedType(String selectedType) {
		this.selectedType = selectedType;
	}

	public String getSelectedType() {
		return selectedType;
	}
	public String getDocketId() {
		return docketId;
	}

	public void setDocketId(String docketId) {
		this.docketId = docketId;
	}
}